<script type="text/javascript">

/**
 * Tic-Tac-Toe static object controller namespace
 */
var TTT = {
   Keys: {
       NAME: "name",
       SCORE: "score"
   },
   RequestKeys: {
       VIEWERDATA: "viewer_data",
       VIEWER: "v"
   },
   Players: {
       Computer: "O",
       Human: "X"
   },
   /**
    * Actual Tic-Tac-Toe game engine.
    */
   Game: function(){

       var me = this;
       var cellbackEmpty = "#555";
       var cellbackWin = "#88E";


       /**
        * Clear the game and reset
        */
       this.clear = function(){
           var i;
           for(i = 0; i < this.gameCells.length; i++){
               this.gameCells[i].innerHTML = "";
               this.gameCells[i].style.backgroundColor = cellbackEmpty;
           }
           this.moves = new Array(9);
           this.hasWinner = false;
           this.winningCells = null;
           this.currentPlayer = TTT.Players.Human;
       }

       /**
        * Colors background on winning cells
        */
       this.markWinningCells = function(){
           if(!this.winningCells) return;
           for(var i = 0; i < this.winningCells.length; i++){
               this.gameCells[this.winningCells[i]].style.backgroundColor = cellbackWin;
           }
       }

       /**
        * Flag to indicate a winner was found
        */
       this.hasWinner = false;

       /**
        * Identify the cells in the winning line
        */
       this.winningCells = null;

       /**
        * Last person to win - player or computer
        */
       this.lastWinner = null;
       
       /**
        * The player who is currently allowed to make a move
        */
       this.currentPlayer = TTT.Players.Human;

       function init(){
           me.displayBoardElem = document.getElementById("gameboard");
           me.gameCells = me.displayBoardElem.getElementsByTagName("td");
           me.moves = new Array(9);
           me.messageBlock = document.getElementById("messages");
           me.clear();
       }

       init();
   }
};

/**
 * Game object method defintions
 */
TTT.Game.prototype = {

   writeMessage: function(message, color){
       if(color){
           this.messageBlock.innerHTML += "<span style='color:" + color + ";'>" + message + "</span>";
       }
       else{
           this.messageBlock.innerHTML += message;
       }
   },

   /**
    * Makes a move and records the result.
    * Draws the move on the game board
    * @param {Object} player
    * @param {Object} position
    */
   makeMove : function(player, position){
       if(player !== this.currentPlayer) return;
       
       this.lookForWin();
       if(!this.hasWinner){
           if(!this.moves[position]){
               this.moves[position] = player;
               this._drawMove(player, position);
               this.lookForWin();
           }
           else{
               writeMessage("Invalid Move for " + player, "red");
           }
           
           this.currentPlayer = (player === TTT.Players.Human) ? TTT.Players.Computer : TTT.Players.Human;
       }
       if(this.hasWinner){
           this.markWinningCells();
       }
   },
   /**
    * Draws the player's mark in the cell
    * @param {Object} player
    * @param {Object} position
    */
   _drawMove: function(player, position){
       this.gameCells[position].innerHTML = player;
   },

   /**
    * Intense AI to compete in most difficult tick-tack-toe tournaments
    */
   makeComputerMove : function(){
       var die = 50;
       var pos;
       var found = false;
       var i=0;
       while(!found && i++ < die){
           pos = new Date().getMilliseconds() % 10;
           if(pos == 9) pos = 8;
           found = (!this.moves[pos]);
       }
       if(!found){
           for(i=0; i < 9; i++){
               if(!this.moves[i]){
                   this.makeMove(TTT.Players.Computer, i);
                   return;
               }
           }
           alert('no move');
           return;
       }
       else{
           this.makeMove(TTT.Players.Computer, pos);
       }
   },


   lookForWin: function(){
       //horizontal
       var i=0;
       for(i=0; i<9; i=i+3){
           this.hasWinner = this.matchMovePositions(i,i+1,i+2);
           if(this.hasWinner){
               this.winningCells = [i,i+1,i+2]
               return;
           }
       }
       
       //vertical
       for(i=0; i<3; i++){
           this.hasWinner = this.matchMovePositions(i,i+3,i+6);
           if(this.hasWinner){
               this.winningCells = [i,i+3,i+6]
               return;
           }
       }
       
       //diag
       if(!this.hasWinner){
           this.hasWinner = this.matchMovePositions(0,4,8);
           if(this.hasWinner){
               this.winningCells = [0,4,8]
           }
       }
       if(!this.hasWinner){
           this.hasWinner = this.matchMovePositions(2,4,6);
           if(this.hasWinner){
               this.winningCells = [2,4,6]
           }
       }

   },

   /**
    * Tests three positions to see if they match
    * @param {Object} a
    * @param {Object} b
    * @param {Object} c
    */
   matchMovePositions : function(a, b, c){
       if(this.moves[a]){
           return (this.moves[a] == this.moves[b] && this.moves[a] == this.moves[c]);
       }
       return false;
   }
};

var currentGame = null;

function makePlayerMove(e){
   if(!e) var e = window.event;

   var cell = (e.target) ? e.target.getAttribute("gamecell") : e.srcElement.getAttribute("gamecell");
   currentGame.makeMove(TTT.Players.Human, cell);
   if(!currentGame.hasWinner){
       window.setTimeout(function(){
           currentGame.makeComputerMove();
       }, 500);
   }

}

/**
 * Function called by the onload handler and the entry point for the app
 */
function initializeGame(){
   if(currentGame){
       currentGame.clear();
   }
   else{
       currentGame = new TTT.Game();
   }
}

//register to look for initial data
gadgets.util.registerOnLoadHandler(initializeGame);

</script>

<div id="container">
   <h1>OpenSocial Tic-Tac-Toe</h1>

   <table id="gameboard" onclick="makePlayerMove(event)">
       <tr>
           <td gamecell="0"></td>

           <td gamecell="1"></td>
           <td gamecell="2"></td>
       </tr>
       <tr>
           <td gamecell="3"></td>
           <td gamecell="4"></td>
           <td gamecell="5"></td>
       </tr>
       <tr>

           <td gamecell="6"></td>
           <td gamecell="7"></td>
           <td gamecell="8"></td>
       </tr>
   </table>

   <button onclick="initializeGame();">New Game</button>
</div>

<style>

img
{
   border:0;
}
body
{
   margin:0;
   padding:0;
   font-family:Verdana;
   font-size:12pt;
}

#gameboard
{
	margin:10px;
   border-collapse: collapse;
   border:2px solid black;
   padding:5px;
   margin-bottom:5px;
   empty-cells:show;
   font-size: 40pt;
   font-family:Verdana;
   font-weight:bold;
   color:#fff;
   cursor:pointer;
}
#gameboard td
{
   background:#555;
   color:#fff;
   border:1px solid white;
   text-align:center;
   width:120px;
   height:120px;
}
#container
{
	margin:10px;
}
#messages
{
   height:20px;
   overflow:auto;
   color:Red;
}

</style>